å®äžçã®ã«ã¡ã©ãã©ã¡ãŒã¿ãã£ãªãã¬ãŒã·ã§ã³ã«é¢ããå°éæè¡ãåŠã³ãæ£ç¢ºã§ã·ãŒã ã¬ã¹ãªä»®æ³ãªãŒããŒã¬ã€ãå®çŸããããšã§ãWebXRã®ããã³ã·ã£ã«ãæå€§éã«åŒãåºããŸãã
WebXRã«ã¡ã©ãã£ãªãã¬ãŒã·ã§ã³ïŒæ²¡å ¥åäœéšã®ããã®å®äžçãã©ã¡ãŒã¿èª¿æŽããã¹ã¿ãŒãã
WebXRã®ç»å Žã«ãããæ²¡å ¥åæè¡ã¯æ°äž»åãããæ¡åŒµçŸå®ïŒARïŒãä»®æ³çŸå®ïŒVRïŒã®äœéšããŠã§ããã©ãŠã¶ã«çŽæ¥ããããããŸãããããããçã«ã·ãŒã ã¬ã¹ã§ä¿¡ææ§ã®é«ãè€åçŸå®ã¢ããªã±ãŒã·ã§ã³ãç¹ã«ä»®æ³ã³ã³ãã³ããçŸå®äžçã«éãåããããã®ãå¶äœããã«ã¯ãéèŠã§ãããªããèŠéããããã¡ãªããã»ã¹ãããªãã¡WebXRã«ã¡ã©ãã£ãªãã¬ãŒã·ã§ã³ãäžå¯æ¬ ã§ãããã®ããã»ã¹ã¯ãçŸå®äžçã®ç°å¢ãæããç©ççãªã«ã¡ã©ã®ãã©ã¡ãŒã¿ãæ£ç¢ºã«æ±ºå®ããä»®æ³ãªããžã§ã¯ããšç©ç空éãšã®ç²Ÿå¯ãªäœçœ®åãããå¯èœã«ããŸãã
äžçäžã®éçºè ã«ãšã£ãŠãå ç¢ãªã«ã¡ã©ãã£ãªãã¬ãŒã·ã§ã³æè¡ãçè§£ãå®è£ ããããšã¯ãå¿ å®åºŠã®é«ãARãªãŒããŒã¬ã€ãæ£ç¢ºãª3Dåæ§æããããŠçã«æ²¡å ¥æã®ãããŠãŒã¶ãŒäœéšãå®çŸããããã®æéèŠèª²é¡ã§ãããã®å æ¬çãªã¬ã€ãã§ã¯ãWebXRã«ã¡ã©ãã£ãªãã¬ãŒã·ã§ã³ã®è€éããæãäžãããã®åºæ¬ååãå®è·µçãªæ¹æ³è«ããããŠå€æ§ãªã°ããŒãã«ã³ã³ããã¹ãã§æŽ»åããéçºè ãçŽé¢ããçŸå®äžçã®èª²é¡ã«ã€ããŠè§£èª¬ããŸãã
ãªãWebXRã«ã¡ã©ãã£ãªãã¬ãŒã·ã§ã³ã¯äžå¯æ¬ ãªã®ãïŒ
WebXRã¢ããªã±ãŒã·ã§ã³ã§ã¯ããã©ãŠã¶ã®ARæ©èœãéåžžããŠãŒã¶ãŒã®ããã€ã¹ã«ã¡ã©ããã®ã©ã€ããããªãã£ãŒããæäŸããŸããä»®æ³ãªããžã§ã¯ãããã®çŸå®äžçã®ãã¥ãŒã«èª¬åŸåãæã£ãŠçµ±åãããŠããããã«èŠããããã«ã¯ããã®3Däœçœ®ãšåããã«ã¡ã©ã®èŠç¹ã«å¯ŸããŠç¶¿å¯ã«èšç®ããå¿ èŠããããŸããããã«ã¯ãã«ã¡ã©ãã©ã®ããã«äžçããèŠãŠãããããæ£ç¢ºã«ç¥ãããšãæ±ããããŸãã
ã«ã¡ã©ãã£ãªãã¬ãŒã·ã§ã³ã«ãã£ãŠã以äžã®2ã€ã®éèŠãªãã©ã¡ãŒã¿ã»ãããå®çŸ©ããããšãã§ããŸãïŒ
- ã«ã¡ã©ã®å
éšãã©ã¡ãŒã¿ïŒãããã¯ã空éå
ã§ã®äœçœ®ãåããšã¯ç¡é¢ä¿ãªãã«ã¡ã©ã®å
éšçãªå
åŠçç¹æ§ãèšè¿°ããŸããå«ãŸãããã®ã¯ä»¥äžã®éãã§ãïŒ
- çŠç¹è·é¢ïŒfx, fyïŒïŒã¬ã³ãºã®å åŠäžå¿ããç»åã»ã³ãµãŒãŸã§ã®è·é¢ããã¯ã»ã«åäœã§æž¬å®ãããã®ã
- äž»ç¹ïŒcx, cyïŒïŒå åŠäžå¿ã®ç»åå¹³é¢ãžã®æåœ±ãçæ³çã«ã¯ãç»åã®äžå¿ã«ãããŸãã
- æªã¿ä¿æ°ïŒã«ã¡ã©ã¬ã³ãºã«ãã£ãŠåŒãèµ·ããããéç·åœ¢ãªæªã¿ãäŸãã°æŸå°ç¶æªã¿ïŒæšœåãŸãã¯ç³žå·»ãåïŒãæ¥ç·æªã¿ãã¢ãã«åããŸãã
- ã«ã¡ã©ã®å€éšãã©ã¡ãŒã¿ïŒãããã¯ã3Däžç座æšç³»ã«ãããã«ã¡ã©ã®å§¿å¢ïŒäœçœ®ãšåãïŒãå®çŸ©ããŸããéåžžãå転è¡åãšäžŠé²ãã¯ãã«ã§è¡šçŸãããŸãã
æ£ç¢ºãªå éšã»å€éšãã©ã¡ãŒã¿ããªããã°ãä»®æ³ãªããžã§ã¯ãã¯äœçœ®ããããããæªãã ããçŸå®äžçã®ã·ãŒã³ããä¹é¢ããŠèŠããŠããŸããŸããããã«ããæ²¡å ¥æã®å¹»æ³ãå£ããARã¢ããªã±ãŒã·ã§ã³ã䜿ãç©ã«ãªããªããªãå¯èœæ§ããããŸãã
ã«ã¡ã©ãã£ãªãã¬ãŒã·ã§ã³ã®èåŸã«ããæ°åŠãçè§£ãã
ã«ã¡ã©ãã£ãªãã¬ãŒã·ã§ã³ã®åºç€ã¯ããã°ãã°ãã³ããŒã«ã«ã¡ã©ã¢ãã«ããå°ãããã³ã³ãã¥ãŒã¿ããžã§ã³ã®ååã«ãããŸããäžç座æšã«ããã3Dç¹P = [X, Y, Z, 1]Tã®2Dç»åç¹p = [u, v, 1]Tãžã®æåœ±ã¯ã次ã®ããã«è¡šçŸã§ããŸãïŒ
s * p = K * [R | t] * P
ããã§ïŒ
- sã¯ã¹ã±ãŒã«ãã¡ã¯ã¿ãŒã§ãã
- Kã¯å
éšãã©ã¡ãŒã¿è¡åã§ãïŒ
K = [[fx, 0, cx], [0, fy, cy], [0, 0, 1]]
- [R | t]ã¯å€éšãã©ã¡ãŒã¿è¡åã§ã3x3ã®å転è¡åïŒRïŒãš3x1ã®äžŠé²ãã¯ãã«ïŒtïŒãçµã¿åããããã®ã§ãã
- Pã¯å次座æšã«ããã3Dç¹ã§ãã
- pã¯å次座æšã«ããã2Dç»åç¹ã§ãã
ã¬ã³ãºã®æªã¿ã¯ããã®ã¢ãã«ãããã«è€éã«ããŸããäŸãã°ãæŸå°ç¶æªã¿ã¯æ¬¡ã®ããã«ã¢ãã«åã§ããŸãïŒ
x' = x * (1 + k1*r^2 + k2*r^4 + k3*r^6)
y' = y * (1 + k1*r^2 + k2*r^4 + k3*r^6)
ããã§(x, y)ã¯æªãã 座æšã(x', y')ã¯çæ³çãªæªã¿ã®ãªã座æšãr^2 = x^2 + y^2ããããŠk1, k2, k3ã¯æŸå°ç¶æªã¿ä¿æ°ã§ãã
ãã£ãªãã¬ãŒã·ã§ã³ã®ç®æšã¯ãæ¢ç¥ã®3Däžçç¹ãšç»åå ã§ã®ãã®2Dæåœ±ãšã®éã®èŠ³æž¬ããã察å¿é¢ä¿ãæããã説æããfx, fy, cx, cy, k1, k2, k3, R, tã®å€ãèŠã€ããããšã§ãã
WebXRã«ã¡ã©ãã£ãªãã¬ãŒã·ã§ã³ã®æ¹æ³
WebXRã¢ããªã±ãŒã·ã§ã³çšã®ã«ã¡ã©ãã©ã¡ãŒã¿ãååŸããã«ã¯ãäž»ã«2ã€ã®ã¢ãããŒãããããŸãïŒ
1. å èµã®WebXR Device APIæ©èœã䜿çšãã
çŸä»£ã®WebXR APIãç¹ã«ARCoreïŒAndroidäžïŒãARKitïŒiOSäžïŒã掻çšãããã®ã¯ãã«ã¡ã©ãã£ãªãã¬ãŒã·ã§ã³ã®å€§éšåãèªåçã«åŠçããããšããããããŸãããããã®ãã©ãããã©ãŒã ã¯ãSLAMïŒèªå·±äœçœ®æšå®ãšç°å¢å°å³äœæã®åæå®è¡ïŒã«åºã¥ãé«åºŠãªã¢ã«ãŽãªãºã ãçšããŠãããã€ã¹ã®åãã远跡ããã«ã¡ã©ã®å§¿å¢ããªã¢ã«ã¿ã€ã ã§æšå®ããŸãã
- ARCoreãšARKitïŒãããã®SDKã¯ãæšå®ãããã«ã¡ã©è¡åãšå§¿å¢æ å ±ãæäŸããŸããå éšãã©ã¡ãŒã¿ã¯éåžžãããã€ã¹ã®ãã©ãŒã«ã¹ããºãŒã ã倿Žãããããç°å¢ãããããçè§£ããããããã«ã€ããŠåçã«æŽæ°ãããŸããå€éšãã©ã¡ãŒã¿ïŒã«ã¡ã©ã®å§¿å¢ïŒã¯ããŠãŒã¶ãŒãããã€ã¹ãåãããšç¶ç¶çã«æŽæ°ãããŸãã
XRWebGLLayerãš`getProjectionMatrix()`ïŒWebXRå ã®WebGLã³ã³ããã¹ãã§ã¯ãXRWebGLLayerã¯`getProjectionMatrix()`ã®ãããªã¡ãœãããæäŸããŸãããããã¯ããã€ã¹ã®æšå®ãããã«ã¡ã©å éšãã©ã¡ãŒã¿ãšç®çã®ãã¥ãŒã«åºã¥ããŠæ å ±ãåŸãŸãããã®è¡åã¯ãä»®æ³ãªããžã§ã¯ããã«ã¡ã©ã®èŠéå°ã«æ£ããåãããŠã¬ã³ããªã³ã°ããããã«äžå¯æ¬ ã§ããXRFrame.getViewerPose()ïŒãã®ã¡ãœããã¯XRViewerPoseãªããžã§ã¯ããè¿ããŸããããã«ã¯ãXRãªã°ã®åº§æšç³»ã«å¯Ÿããã«ã¡ã©ã®äœçœ®ãšåãïŒå€éšãã©ã¡ãŒã¿ïŒãå«ãŸããŠããŸãã
å©ç¹ïŒ
- 䜿ããããïŒéçºè ã¯è€éãªãã£ãªãã¬ãŒã·ã§ã³ã¢ã«ãŽãªãºã ãäžããå®è£ ããå¿ èŠããããŸããã
- ãªã¢ã«ã¿ã€ã é©å¿ïŒã·ã¹ãã ããã©ã¡ãŒã¿ãç¶ç¶çã«æŽæ°ããç°å¢ã®å€åã«é©å¿ããŸãã
- å¹ åºãããã€ã¹ãµããŒãïŒæçãããã€ãã£ãARãã¬ãŒã ã¯ãŒã¯ã掻çšããŸãã
æ¬ ç¹ïŒ
- ãã©ãã¯ããã¯ã¹ïŒãã£ãªãã¬ãŒã·ã§ã³ããã»ã¹ãšãã©ã¡ãŒã¿ã«å¯Ÿããå¶åŸ¡ãéãããŠããŸãã
- ãã©ãããã©ãŒã äŸåæ§ïŒããã€ã¹ãšãã©ãŠã¶ã®åºç€ãšãªãARæ©èœã«äŸåããŸãã
- 粟床ã®éçïŒããã©ãŒãã³ã¹ã¯ç°å¢æ¡ä»¶ïŒç §æããã¯ã¹ãã£ïŒã«ãã£ãŠå€åããå¯èœæ§ããããŸãã
2. æšæºãã¿ãŒã³ã«ããæåãã£ãªãã¬ãŒã·ã§ã³
éåžžã«é«ã粟床ãã«ã¹ã¿ã ãã£ãªãã¬ãŒã·ã§ã³ãå¿ èŠãšããã¢ããªã±ãŒã·ã§ã³ããŸãã¯ããã€ã¹ã®å èµARæ©èœãäžååãŸãã¯å©çšã§ããªãå Žåãæšæºåããããã£ãªãã¬ãŒã·ã§ã³ãã¿ãŒã³ã䜿çšããæåãã£ãªãã¬ãŒã·ã§ã³ãå¿ èŠã§ããããã¯ããã¹ã¯ãããARã¢ããªã±ãŒã·ã§ã³ãç¹æ®ãªããŒããŠã§ã¢ã§ããäžè¬çã§ãã
æãäžè¬çãªæ¹æ³ã¯ããã§ãã«ãŒããŒããã¿ãŒã³ã䜿çšããããšã§ãã
ããã»ã¹ïŒ
- ãã§ãã«ãŒããŒããã¿ãŒã³ã®äœæïŒæ¢ç¥ã®å¯žæ³ïŒäŸïŒåæ£æ¹åœ¢ã¯3cm x 3cmïŒã®ãã§ãã«ãŒããŒããã¿ãŒã³ãå¹³ããªé¢ã«å°å·ããŸããæ£æ¹åœ¢ã®ãµã€ãºãšåèŸºã®æ£æ¹åœ¢ã®æ°ã¯éèŠã§ãããæ£ç¢ºã«ç¥ãããŠããå¿ èŠããããŸãã ã°ããŒãã«ãªèæ ®äºé ïŒå°å·ç©ãå®å šã«å¹³ãã§ãæªã¿ããªãããšã確èªããŸããã¢ãŒãã£ãã¡ã¯ããæå°éã«æããããã«ãå°å·è§£å床ãšçŽ æãèæ ®ããŠãã ããã
- è€æ°ã®ç»åããã£ããã£ïŒããŸããŸãªè§åºŠãšè·é¢ãããã§ãã«ãŒããŒãã®åçã倿°æ®åœ±ããåç»åã§ãã§ãã«ãŒããŒããã¯ã£ãããšèŠãããã¬ãŒã ã®ããªãã®éšåãå ããããã«ããŸããèŠç¹ã倿§ã§ããã»ã©ããã£ãªãã¬ãŒã·ã§ã³ã¯ããå ç¢ã«ãªããŸãã ã°ããŒãã«ãªèæ ®äºé ïŒç §ææ¡ä»¶ã¯åçã«å€åããå¯èœæ§ããããŸããã¿ãŒã²ããã®å±éç°å¢ã代衚ããç §æã·ããªãªã§ç»åããã£ããã£ããŸãããã§ãã«ãŒããŒãäžã®åŒ·ã圱ãåå°ã¯é¿ããŠãã ããã
- ãã§ãã«ãŒããŒãã®ã³ãŒããŒãæ€åºïŒã³ã³ãã¥ãŒã¿ããžã§ã³ã©ã€ãã©ãªïŒWebAssemblyçšã«ã³ã³ãã€ã«ã§ããOpenCVãªã©ïŒã䜿çšããŠããã§ãã«ãŒããŒãã®å åŽã®ã³ãŒããŒãèªåçã«æ€åºããŸããã©ã€ãã©ãªã¯`cv2.findChessboardCorners()`ã®ãããªé¢æ°ãæäŸããŸãã
- å éšããã³å€éšãã©ã¡ãŒã¿ã®èšç®ïŒè€æ°ã®ç»åã§ã³ãŒããŒãæ€åºãããããã«å¯Ÿå¿ãã3Däžç座æšãïŒãã§ãã«ãŒããŒãã®å¯žæ³ã«åºã¥ããŠïŒããã£ããã`cv2.calibrateCamera()`ã®ãããªã¢ã«ãŽãªãºã ã䜿çšããŠãå éšãã©ã¡ãŒã¿ïŒçŠç¹è·é¢ãäž»ç¹ãæªã¿ä¿æ°ïŒãšåç»åã®å€éšãã©ã¡ãŒã¿ïŒå転ãšäžŠé²ïŒãèšç®ã§ããŸãã
- ãã£ãªãã¬ãŒã·ã§ã³ã®é©çšïŒåŸãããå éšãã©ã¡ãŒã¿ã¯ãå°æ¥ã®ç»åã®æªã¿ãè£æ£ããããä»®æ³ã³ã³ãã³ããã¬ã³ããªã³ã°ããããã®å°åœ±è¡åãæ§ç¯ããããã«äœ¿çšã§ããŸããå€éšãã©ã¡ãŒã¿ã¯ããã§ãã«ãŒããŒãã®åº§æšç³»ã«å¯Ÿããã«ã¡ã©ã®å§¿å¢ãå®çŸ©ããŸãã
ããŒã«ãšã©ã€ãã©ãªïŒ
- OpenCVïŒã³ã³ãã¥ãŒã¿ããžã§ã³ã¿ã¹ã¯ã®äºå®äžã®æšæºã§ãããã«ã¡ã©ãã£ãªãã¬ãŒã·ã§ã³ã®ããã®å æ¬çãªæ©èœãæäŸããŸãããŠã§ããã©ãŠã¶ã§äœ¿çšããããã«WebAssemblyã«ã³ã³ãã€ã«ã§ããŸãã
- PythonãšOpenCVïŒäžè¬çãªã¯ãŒã¯ãããŒã¯ãPythonã䜿çšããŠãªãã©ã€ã³ã§ãã£ãªãã¬ãŒã·ã§ã³ãå®è¡ãããã®ãã©ã¡ãŒã¿ãWebXRã¢ããªã±ãŒã·ã§ã³ã§äœ¿çšããããã«ãšã¯ã¹ããŒãããããšã§ãã
- å°çšãã£ãªãã¬ãŒã·ã§ã³ããŒã«ïŒäžéšã®ãããã§ãã·ã§ãã«ãªARã·ã¹ãã ãããŒããŠã§ã¢ã«ã¯ãç¬èªã®ãã£ãªãã¬ãŒã·ã§ã³ãœãããŠã§ã¢ãä»å±ããŠããå ŽåããããŸãã
å©ç¹ïŒ
- é«ç²ŸåºŠïŒæ£ããå®è¡ãããã°ãéåžžã«ç²Ÿå¯ãªçµæãéæã§ããŸãã
- å®å šãªå¶åŸ¡ïŒéçºè ã¯ãã£ãªãã¬ãŒã·ã§ã³ããã»ã¹ãšãã©ã¡ãŒã¿ãå®å šã«å¶åŸ¡ã§ããŸãã
- ããã€ã¹éäŸåïŒã©ã®ã«ã¡ã©ã«ãé©çšã§ããŸãã
æ¬ ç¹ïŒ
- è€éãªå®è£ ïŒã³ã³ãã¥ãŒã¿ããžã§ã³ã®ååãšæ°åŠã®ååãªçè§£ãå¿ èŠã§ãã
- æéããããïŒãã£ãªãã¬ãŒã·ã§ã³ããã»ã¹ã¯é¢åãªå ŽåããããŸãã
- éçç°å¢ã®èŠä»¶ïŒäž»ã«ã«ã¡ã©ã®å éšãã©ã¡ãŒã¿ãé »ç¹ã«å€åããªãç¶æ³ã«é©ããŠããŸãã
WebXRã«ãããå®è·µçãªèª²é¡ãšè§£æ±ºç
WebXRã¢ããªã±ãŒã·ã§ã³ãã°ããŒãã«ã«å±éããããšã¯ãã«ã¡ã©ãã£ãªãã¬ãŒã·ã§ã³ã«ç¹æã®èª²é¡ããããããŸãïŒ
1. ç°å¢ã®å€æ§æ§
課é¡ïŒç §ææ¡ä»¶ãåå°é¢ããã¯ã¹ãã£ã®ä¹ããç°å¢ã¯ãARãã©ããã³ã°ãšãã£ãªãã¬ãŒã·ã§ã³ã®ç²ŸåºŠã«å€§ããªåœ±é¿ãäžããå¯èœæ§ããããŸããæ±äº¬ã®æãããªãã£ã¹ã§å®è¡ããããã£ãªãã¬ãŒã·ã§ã³ã¯ããµã³ããŠãã®èæãã«ãã§ããã©ã±ã·ã¥ã®æ¥åœããã®è¯ãå±å€åžå Žã§ã¯ããŸãæ©èœããªããããããŸããã
解決çïŒ
- å ç¢ãªSLAMïŒããŸããŸãªæ¡ä»¶ã«å¯ŸããŠå埩åãããããã«èšèšãããçŸä»£ã®ARãã¬ãŒã ã¯ãŒã¯ïŒARCoreãARKitïŒã«äŸåããŸãã
- ãŠãŒã¶ãŒã¬ã€ãã³ã¹ïŒãŠãŒã¶ãŒãååãªãã¯ã¹ãã£ã®ããæããå ŽæãèŠã€ããã®ãå©ããããã«ãæç¢ºãªç»é¢äžã®æç€ºãæäŸããŸããäŸãã°ããããã€ã¹ãåãããŠãšãªã¢ãã¹ãã£ã³ããŠãã ããããããã¯ã¹ãã£ã®ãã衚é¢ã«åããŠãã ããããªã©ã
- ããŒã«ãŒããŒã¹ARïŒãã©ãŒã«ããã¯ãšããŠïŒïŒæ£ç¢ºãªãã©ããã³ã°ãæéèŠã§ããéèŠãªã¢ããªã±ãŒã·ã§ã³ã§ã¯ãfiducialããŒã«ãŒïŒARUcoããŒã«ãŒãQRã³ãŒããªã©ïŒã®äœ¿çšãæ€èšããŸãããããã¯ãå°é£ãªç°å¢ã§ãARã³ã³ãã³ãã®å®å®ããã¢ã³ã«ãŒãã€ã³ããæäŸããŸããçã®ã«ã¡ã©ãã£ãªãã¬ãŒã·ã§ã³ã§ã¯ãããŸããããç¹å®ã®é åã®äœçœ®åããåé¡ã广çã«è§£æ±ºããŸãã
- ããã°ã¬ãã·ããã£ãªãã¬ãŒã·ã§ã³ïŒäžéšã®ã·ã¹ãã ã¯ããŠãŒã¶ãŒãã¢ããªã±ãŒã·ã§ã³ãšå¯Ÿè©±ããã«ã€ããŠç°å¢ã®çè§£ãæŽç·Žããããäžçš®ã®ããã°ã¬ãã·ããã£ãªãã¬ãŒã·ã§ã³ãå®è¡ã§ããŸãã
2. ããã€ã¹ã®å€æ§æ§
課é¡ïŒäžçäžã®ã¢ãã€ã«ããã€ã¹ã®çš®é¡ã®å€ãã¯ãã«ã¡ã©ã»ã³ãµãŒãã¬ã³ãºã®å質ãåŠçèœåãç°ãªãããšãæå³ããŸãããã©ãã°ã·ããããã€ã¹çšã«æé©åããããã£ãªãã¬ãŒã·ã§ã³ãããããã¬ã³ãžãæ§åã®ããã€ã¹ã«å®å šã«é©åãããšã¯éããŸããã
解決çïŒ
- åçãªå éšãã©ã¡ãŒã¿æšå®ïŒWebXRãã©ãããã©ãŒã ã¯éåžžãå éšãã©ã¡ãŒã¿ãåçã«æšå®ããããšãç®æããŠããŸããããã€ã¹ã®ã«ã¡ã©èšå®ïŒãã©ãŒã«ã¹ãé²åºãªã©ïŒã倿Žãããå ŽåãARã·ã¹ãã ã¯çæ³çã«ã¯é©å¿ãã¹ãã§ãã
- ããã€ã¹éã§ã®ãã¹ãïŒããŸããŸãªã¡ãŒã«ãŒãæ§èœå±€ã代衚ãã倿§ãªã¿ãŒã²ããããã€ã¹ã§åŸ¹åºçãªãã¹ãã宿œããŸãã
- æœè±¡åã¬ã€ã€ãŒïŒããã€ã¹åºæã®éããå¯èœãªéãæœè±¡åããWebXRãã¬ãŒã ã¯ãŒã¯ã䜿çšããŸãã
3. æªã¿ã¢ãã«ã®éç
課é¡ïŒåçŽãªæªã¿ã¢ãã«ïŒäŸïŒå°æ°ã®æŸå°ç¶ããã³æ¥ç·ä¿æ°ã®ã¿ã䜿çšïŒã¯ããã¹ãŠã®ã¬ã³ãºãç¹ã«äžéšã®ã¢ãã€ã«ããã€ã¹ã§äœ¿çšãããåºè§ã¬ã³ãºãéçŒã¬ã³ãºã®è€éãªæªã¿ãå®å šã«ã¯èª¬æã§ããªãå ŽåããããŸãã
解決çïŒ
- 髿¬¡ã®æªã¿ä¿æ°ïŒæåãã£ãªãã¬ãŒã·ã§ã³ãå®è¡ããå Žåãããžã§ã³ã©ã€ãã©ãªããµããŒãããŠããã°ãããå€ãã®æªã¿ä¿æ°ïŒäŸïŒk4ãk5ãk6ïŒãå«ããããšãå®éšããŸãã
- å€é åŒãŸãã¯èæ¿ã¹ãã©ã€ã³ã¢ãã«ïŒæ¥µç«¯ãªæªã¿ã«å¯ŸããŠã¯ãããé«åºŠãªéç·åœ¢ãããã³ã°æè¡ãå¿ èŠã«ãªãå ŽåããããŸããããããã¯èšç®ã³ã¹ãã®ããããªã¢ã«ã¿ã€ã ã®WebXRã¢ããªã±ãŒã·ã§ã³ã§ã¯ããŸãäžè¬çã§ã¯ãããŸããã
- äºåèšç®ãããæªã¿ãããïŒæ¢ç¥ã§äžè²«ããã¬ã³ãºæªã¿ãæã€ããã€ã¹ã®å Žåãæªã¿è£æ£ã®ããã®äºåèšç®ãããã«ãã¯ã¢ããããŒãã«ïŒLUTïŒã¯éåžžã«å¹æçã§èšç®å¹çãé«ãã§ãã
4. 座æšç³»ã®äžè²«æ§
課é¡ïŒç°ãªãARãã¬ãŒã ã¯ãŒã¯ãWebXR APIã®ç°ãªãéšåã§ããããããã«ç°ãªã座æšç³»ã®èŠçŽïŒäŸïŒYã¢ãã察YããŠã³ã軞ã®å©ãæïŒã䜿çšããå ŽåããããŸããã«ã¡ã©ã®å§¿å¢ãšä»®æ³ãªããžã§ã¯ãã®å€æã®äžè²«ããè§£éã確ä¿ããããšãéèŠã§ãã
解決çïŒ
- APIèŠçŽã®çè§£ïŒäœ¿çšããŠããç¹å®ã®WebXR APIãŸãã¯ãã¬ãŒã ã¯ãŒã¯ã§äœ¿çšãããŠãã座æšç³»ïŒäŸïŒ`XRFrame.getViewerPose()`ã§äœ¿çšããã座æšç³»ïŒãããçè§£ããŸãã
- 倿è¡åã®äœ¿çšïŒå€æè¡åãäžè²«ããŠäœ¿çšããŸããå転ãšäžŠé²ãæ£ããé åºã§ãæ£ãã軞ã«å¯ŸããŠé©çšãããŠããããšã確èªããŸãã
- äžç座æšç³»ã®å®çŸ©ïŒã¢ããªã±ãŒã·ã§ã³ã®äžè²«ããäžç座æšç³»ãæç€ºçã«å®çŸ©ããããã«åŸããŸããããã«ã¯ãWebXR APIããååŸããå§¿å¢ãã¢ããªã±ãŒã·ã§ã³ã®å¥œã¿ã®ã·ã¹ãã ã«å€æããããšãå«ãŸããå ŽåããããŸãã
5. ãªã¢ã«ã¿ã€ã ããã©ãŒãã³ã¹ãšèšç®ã³ã¹ã
課é¡ïŒè€éãªãã£ãªãã¬ãŒã·ã§ã³æé ãæªã¿è£æ£ã¯èšç®éçŽçã§ããå¯èœæ§ããããç¹ã«ãŠã§ããã©ãŠã¶ç°å¢å ã®äœæ§èœããã€ã¹ã§ããã©ãŒãã³ã¹ã®åé¡ãåŒãèµ·ããå¯èœæ§ããããŸãã
解決çïŒ
- ã¢ã«ãŽãªãºã ã®æé©åïŒWebAssemblyã§ã³ã³ãã€ã«ãããOpenCVã®ãããªæé©åãããã©ã€ãã©ãªã䜿çšããŸãã
- GPUã¢ã¯ã»ã©ã¬ãŒã·ã§ã³ïŒããããµããŒããããã¬ãŒã ã¯ãŒã¯ïŒäŸïŒWebGPUïŒã䜿çšããŠããå Žåãã¬ã³ããªã³ã°ãäžéšã®ããžã§ã³ã¿ã¹ã¯ã«GPUãæŽ»çšããŸãã
- ç°¡ç¥åãããã¢ãã«ïŒå¯èœãªå Žåã¯ã蚱容ã§ãã粟床ãæäŸãããªãã°ãããåçŽãªæªã¿ã¢ãã«ã䜿çšããŸãã
- èšç®ã®ãªãããŒãïŒè€éãªãªãã©ã€ã³ãã£ãªãã¬ãŒã·ã§ã³ã®å ŽåããµãŒããŒãŸãã¯ãã¹ã¯ãããã¢ããªã±ãŒã·ã§ã³ã§å®è¡ãããã£ãªãã¬ãŒã·ã§ã³ããããã©ã¡ãŒã¿ãã¯ã©ã€ã¢ã³ãã«éä¿¡ããŸãã
- ãã¬ãŒã ã¬ãŒã管çïŒãã£ãªãã¬ãŒã·ã§ã³ã®æŽæ°ãšã¬ã³ããªã³ã°ãããã€ã¹ã®èœåãè¶ ããªãããã«ããã¹ã ãŒãºãªãã¬ãŒã ã¬ãŒããåªå ããŸãã
é«åºŠãªæè¡ãšä»åŸã®æ¹åæ§
WebXRæè¡ãæçããã«ã€ããŠãã«ã¡ã©ãã£ãªãã¬ãŒã·ã§ã³ãšå§¿å¢æšå®ã®æè¡ãé²åããŠããŸãïŒ
- ãã«ãã«ã¡ã©ãã£ãªãã¬ãŒã·ã§ã³ïŒè€æ°ã®ã«ã¡ã©ã䜿çšããã¢ããªã±ãŒã·ã§ã³ïŒäŸïŒç¹æ®ãªARãããã»ããããããããã©ãããã©ãŒã ïŒã§ã¯ãã«ã¡ã©éã®çžå¯Ÿçãªå§¿å¢ããã£ãªãã¬ãŒã·ã§ã³ããããšããçµ±äžããããã¥ãŒãäœæãããã3Dåæ§æãè¡ã£ããããããã«äžå¯æ¬ ã§ãã
- ã»ã³ãµãŒãã¥ãŒãžã§ã³ïŒã«ã¡ã©ããŒã¿ãIMUïŒæ £æ§èšæž¬è£ çœ®ïŒãªã©ã®ä»ã®ã»ã³ãµãŒãšçµã¿åãããããšã§ãç¹ã«èŠèŠçãªãã©ããã³ã°ã倱æããå¯èœæ§ã®ããç°å¢ã§ããã©ããã³ã°ã®å ç¢æ§ãšç²ŸåºŠãå€§å¹ ã«åäžãããããšãã§ããŸããããã¯SLAMã·ã¹ãã ã®äžå¿çãªååã§ãã
- AIãæŽ»çšãããã£ãªãã¬ãŒã·ã§ã³ïŒæ©æ¢°åŠç¿ã¢ãã«ã¯ãããå ç¢ãªç¹åŸŽæ€åºãæªã¿è£æ£ãããã«ã¯ãšã³ãããŒãšã³ãã®ã«ã¡ã©å§¿å¢æšå®ã«ãŸããŸã䜿çšãããŠãããæç€ºçãªãã£ãªãã¬ãŒã·ã§ã³ãã¿ãŒã³ãžã®äŸåãæžããå¯èœæ§ããããŸãã
- ãšããžã³ã³ãã¥ãŒãã£ã³ã°ïŒããå€ãã®ãã£ãªãã¬ãŒã·ã§ã³ã¿ã¹ã¯ãããã€ã¹äžã§çŽæ¥å®è¡ããïŒãšããžã³ã³ãã¥ãŒãã£ã³ã°ïŒããšã§ãé å»¶ãæžããããªã¢ã«ã¿ã€ã ã®å¿çæ§ãåäžãããããšãã§ããŸãããå¹ççãªã¢ã«ãŽãªãºã ãå¿ èŠã§ãã
ããªãã®WebXRãããžã§ã¯ãã«ãã£ãªãã¬ãŒã·ã§ã³ãå®è£ ãã
ã¢ãã€ã«ããã€ã¹ã察象ãšããã»ãšãã©ã®å žåçãªWebXRã¢ããªã±ãŒã·ã§ã³ã§ã¯ãäž»ãªã¢ãããŒãã¯ãã©ãŠã¶ãšåºç€ãšãªãAR SDKã®æ©èœã掻çšããããšã«ãªããŸãã
ã¯ãŒã¯ãããŒäŸïŒæŠå¿µçïŒïŒ
- WebXRã»ãã·ã§ã³ã®åæåïŒARã»ãã·ã§ã³ããªã¯ãšã¹ãããŸãïŒ`navigator.xr.requestSession('immersive-ar')`ïŒã
- ã¬ã³ããªã³ã°ã³ã³ããã¹ãã®èšå®ïŒWebGLãŸãã¯WebGPUã³ã³ããã¹ããèšå®ããŸãã
- XR WebGLã¬ã€ã€ãŒã®ååŸïŒã»ãã·ã§ã³ã«é¢é£ä»ãããã`XRWebGLLayer`ãååŸããŸãã
- ã¢ãã¡ãŒã·ã§ã³ã«ãŒãã®éå§ïŒrequestAnimationFrameã«ãŒããå®è£ ããŸãã
- ãã¬ãŒã æ å ±ã®ååŸïŒåãã¬ãŒã ã§`session.requestAnimationFrame()`ãåŒã³åºããŸãã
- ãã¥ãŒã¢ã®å§¿å¢ãååŸïŒã¢ãã¡ãŒã·ã§ã³ã³ãŒã«ããã¯å ã§ãçŸåšã®`XRFrame`ã®`XRViewerPose`ãååŸããŸãïŒ`const viewerPose = frame.getViewerPose(referenceSpace);`ãããã«ãããã«ã¡ã©ã®å€éšãã©ã¡ãŒã¿ïŒäœçœ®ãšåãïŒãæäŸãããŸãã
- å°åœ±è¡åã®ååŸïŒ`XRWebGLLayer`ã䜿çšããŠå°åœ±è¡åãååŸããŸããããã«ã¯å éšãã©ã¡ãŒã¿ãšèŠéå°ãçµã¿èŸŒãŸããŠããŸãïŒ`const projectionMatrix = xrLayer.getProjectionMatrix(view);`ã
- ä»®æ³ã·ãŒã³ã®æŽæ°ïŒ`viewerPose`ãš`projectionMatrix`ã䜿çšããŠã3Dã·ãŒã³ïŒäŸïŒThree.jsãBabylon.jsïŒã®ã«ã¡ã©ã®èŠç¹ãæŽæ°ããŸããããã«ã¯ãã«ã¡ã©ã®è¡åãŸãã¯äœçœ®/ã¯ã©ãŒã¿ããªã³ãšå°åœ±è¡åã®èšå®ãå«ãŸããŸãã
- ä»®æ³ãªããžã§ã¯ãã®ã¬ã³ããªã³ã°ïŒä»®æ³ãªããžã§ã¯ããã¯ãŒã«ã座æšã§ã¬ã³ããªã³ã°ããã«ã¡ã©ã®å§¿å¢ã«å¯ŸããŠæ£ãã倿ãããŠããããšã確èªããŸãã
ã«ã¹ã¿ã ãã£ãªãã¬ãŒã·ã§ã³ãå®è¡ããå¿ èŠãããå ŽåïŒäŸïŒç¹å®ã®ã·ãŒã³ããªãã©ã€ã³åŠçã®ããïŒãéåžžã¯PythonãšOpenCVã®ãããªããŒã«ã䜿çšããŠä»¥äžãè¡ããŸãïŒ
- ãã§ãã«ãŒããŒãç»åããã£ããã£ããŸãã
- ã³ãŒããŒãæ€åºããŸãã
- `cv2.calibrateCamera()`ãå®è¡ããŸãã
- çµæã®å éšè¡åïŒ`K`ïŒãšæªã¿ä¿æ°ïŒ`dist`ïŒããã¡ã€ã«ïŒäŸïŒJSONãŸãã¯ãã€ããªåœ¢åŒïŒã«ä¿åããŸãã
ãããã®ä¿åããããã©ã¡ãŒã¿ã¯ãWebXRã¢ããªã±ãŒã·ã§ã³ã«ããŒãããŠãæªãã ç»åãè£æ£ããããWebXR APIã®çµã¿èŸŒã¿è¡åã ãã«é Œããªãå Žåã¯ç¬èªã®å°åœ±è¡åãæ§ç¯ãããããããã«äœ¿çšã§ããŸãããã ããã¢ãã€ã«ã§ã®ã»ãšãã©ã®ãªã¢ã«ã¿ã€ã ARãŠãŒã¹ã±ãŒã¹ã§ã¯ã`XRFrame.getViewerPose()`ãš`XRWebGLLayer.getProjectionMatrix()`ãçŽæ¥å©çšããããšãæšå¥šãããæãå¹ççãªã¢ãããŒãã§ãã
çµè«
WebXRã«ã¡ã©ãã£ãªãã¬ãŒã·ã§ã³ã¯ãä¿¡ææ§ã®é«ãæ¡åŒµçŸå®ããã³è€åçŸå®äœéšã®çžã®äžã®åæã¡ã§ããçŸä»£ã®ARãã©ãããã©ãŒã ã¯è€éãã®å€ããæœè±¡åããŠããŸããããã®åºç€ãšãªãååãæ·±ãçè§£ããããšã¯ããããã°ãæé©åãããã³é«åºŠãªARæ©èœã®éçºã«ãšã£ãŠéåžžã«è²Žéã§ãã
ã«ã¡ã©ã®å éšããã³å€éšãã©ã¡ãŒã¿ã®æŠå¿µããã¹ã¿ãŒããããŸããŸãªãã£ãªãã¬ãŒã·ã§ã³æ¹æ³ãçè§£ããç°å¢ãããã€ã¹ã®å€æ§æ§ã«ãã£ãŠãããããã課é¡ã«ç©æ¥µçã«åãçµãããšã§ãéçºè ã¯æè¡çã«å¥å šã§ããã ãã§ãªããçã«æ²¡å ¥æããããã°ããŒãã«ã«é¢é£æ§ã®ããäœéšãæäŸããWebXRã¢ããªã±ãŒã·ã§ã³ãäœæã§ããŸããããã€ã§ã¢ã¯ã»ã¹å¯èœãªä»®æ³å®¶å ·ã·ã§ãŒã«ãŒã ãããŒãã®å²è·¡ã®ããã®æè²çãªãŒããŒã¬ã€ããŸãã¯ãã«ãªã³ã®ãšã³ãžãã¢åããªã¢ã«ã¿ã€ã ããŒã¿å¯èŠåããŒã«ãæ§ç¯ããŠããå Žåã§ããæ£ç¢ºãªã«ã¡ã©ãã£ãªãã¬ãŒã·ã§ã³ã¯ãããªãã®æ²¡å ¥åçŸå®ãæ§ç¯ãããåºç€ã§ãã
WebXRãšã³ã·ã¹ãã ãé²åãç¶ããã«ã€ããŠãããžã¿ã«ãšç©çäžçã®ã·ãŒã ã¬ã¹ãªçµ±åã®ããã®ããŒã«ãšæè¡ãé²åããŸãããããã®é²æ©ã«åžžã«æ³šæãæãããšã§ãéçºè ã¯æ²¡å ¥åãŠã§ãäœéšã§å¯èœãªããšã®éçãæŒãåºããããšãã§ããŸãã